


const EventEmitter = require('events');

class Api extends EventEmitter{
    constructor(apis){

        super();

        for (const name in apis) {
            if (apis.hasOwnProperty(name)) {
                const fn = apis[name];
                if(fn instanceof Function){
                    apis[name] = fn.bind(this);
                }
            }
        }
        this.apis = apis;
    }
    export(){
        return this.apis;
    }
    getMethod(name){
        var method = this.apis[name];
        if (!method) {
        throw new Error('Invalid method name: ' + name);
        }
        return method;
    }
    wrap(name){
      var old = this.apis[name];
        
      this.apis[name] = function() {
          var args = Array.prototype.slice.call(arguments);
          var beforeArgs = ['before:' + name + '()'].concat(args);

          // prevent if trigger return false
          if (this.emit.apply(this, beforeArgs) === false) return;

          var ret = old.apply(this, arguments);
          var afterArgs = ['after:' + name + '()', ret].concat(args);
          this.emit.apply(this, afterArgs);

          return ret;
      };

      this.apis[name] = this.apis[name].bind(this);

      this.apis[name].__isAspected = true;
    }
    before(name, handler){
        let method = this.getMethod(name);
        if (!method.__isAspected) {
            this.wrap.call(this, name);
        }
        this.on('before:' + name + "()", handler);
        return this;
    }
    after(name, handler){
        this.on('after:' + name + "()", handler);
        return this;
    }
}



module.exports = function main(apis){
    return new Api(apis);
}